home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1985 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of California at Berkeley. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- *
- * All recipients should regard themselves as participants in an ongoing
- * research project and hence should feel obligated to report their
- * experiences (good or bad) with these elementary function codes, using
- * the sendbug(8) program, to the authors.
- */
-
- #ifndef lint
- static char sccsid[] = "@(#)floor.c 5.3 (Berkeley) 5/21/88";
- #endif /* not lint */
-
- #if defined(vax)||defined(tahoe)
- #ifdef vax
- #define _0x(A,B) 0x/**/A/**/B
- #else /* vax */
- #define _0x(A,B) 0x/**/B/**/A
- #endif /* vax */
- static long Lx[] = {_0x(0000,5c00),_0x(0000,0000)}; /* 2**55 */
- #define L *(double *) Lx
- #else /* defined(vax)||defined(tahoe) */
- #ifdef __STDC__
- volatile static double L = 2 * 4503599627370496.0E0; /* 2**53 */
- #else
- static double L = 2 * 4503599627370496.0E0; /* 2**53 */
- #endif
- #endif /* defined(vax)||defined(tahoe) */
- #ifdef ds3100
- #define MAXLONG 2147483648.0E0
- #endif
-
- /*
- * floor(x) := the largest integer no larger than x;
- * ceil(x) := -floor(-x), for all real x.
- *
- * Note: Inexact will be signaled if x is not an integer, as is
- * customary for IEEE 754. No other signal can be emitted.
- */
- double
- floor(x)
- double x;
- {
- double y,ceil();
-
- if (
- #if !defined(vax)&&!defined(tahoe)
- x != x || /* NaN */
- #endif /* !defined(vax)&&!defined(tahoe) */
- x >= L) /* already an even integer */
- return x;
- else if (x < (double)0)
- return -ceil(-x);
- /*
- * This will ensure floor() is computed correctly at least for values of x
- * within the range of long's.
- * The algorithm used otherwise gives bogus results on ds3100.
- * E.g.: floor(1.0) = 0.0, floor(-3.0) = -3.0, etc.
- */
- #ifdef ds3100
- else if ( x < MAXLONG )
- return (long)x;
- #endif
- else { /* now 0 <= x < L */
- y = L+x; /* destructive store must be forced */
- y -= L; /* an integer, and |x-y| < 1 */
- return x < y ? y-(double)1 : y;
- }
- }
-
- double
- ceil(x)
- double x;
- {
- double y,floor();
-
- if (
- #if !defined(vax)&&!defined(tahoe)
- x != x || /* NaN */
- #endif /* !defined(vax)&&!defined(tahoe) */
- x >= L) /* already an even integer */
- return x;
- else if (x < (double)0)
- return -floor(-x);
- #ifdef ds3100
- else if ( x < MAXLONG )
- return x == (long)x ? x : (long)x + 1.0;
- #endif
- else { /* now 0 <= x < L */
- y = L+x; /* destructive store must be forced */
- y -= L; /* an integer, and |x-y| < 1 */
- return x > y ? y+(double)1 : y;
- }
- }
-
- #ifndef national /* rint() is in ./NATIONAL/support.s */
- /*
- * algorithm for rint(x) in pseudo-pascal form ...
- *
- * real rint(x): real x;
- * ... delivers integer nearest x in direction of prevailing rounding
- * ... mode
- * const L = (last consecutive integer)/2
- * = 2**55; for VAX D
- * = 2**53; for IEEE 754 Double
- * real s,t;
- * begin
- * if x != x then return x; ... NaN
- * if |x| >= L then return x; ... already an integer
- * s := copysign(L,x);
- * t := x + s; ... = (x+s) rounded to integer
- * return t - s
- * end;
- *
- * Note: Inexact will be signaled if x is not an integer, as is
- * customary for IEEE 754. No other signal can be emitted.
- */
- double
- rint(x)
- double x;
- {
- double s,t,one = 1.0,copysign();
- #if !defined(vax)&&!defined(tahoe)
- if (x != x) /* NaN */
- return (x);
- #endif /* !defined(vax)&&!defined(tahoe) */
- if (copysign(x,one) >= L) /* already an integer */
- return (x);
- s = copysign(L,x);
- t = x + s; /* x+s rounded to integer */
- return (t - s);
- }
- #else /* !national */
- /*
- * The ds3100 defines national but doesn't have the auxiliary routine
- * mentioned above.
- */
- #ifdef ds3100
- double
- rint(x)
- double x;
- {
- register double fx = floor(x);
-
- if ( x - fx < 0.5 /* floor is the nearest int */ ||
- x - fx == 0.5 && fx == 2.0 * floor(fx / 2.0)
- /* floor is the nearest EVEN int */ )
- return fx;
- else
- return fx + 1.0;
- }
- #endif /* ds3100 */
- #endif /* not national */
-